/*
* INSANE - Interactive Structural Analysis Environment
*
* Copyright (C) 2003-2005
* Universidade Federal de Minas Gerais
* Escola de Engenharia
* Departamento de Engenharia de Estruturas
* 
* Author's email :    insane@dees.ufmg.br
* Author's website :  http://www.dees.ufmg.br/insane
* 
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
* 
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
* 
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/
package br.ufmg.dees.insane.materialMedia.constitutiveModel;

import java.util.HashMap;

import br.ufmg.dees.insane.analysisModel.AnalysisModel;
import br.ufmg.dees.insane.continuousPointModel.ContinuousPointModel;
import br.ufmg.dees.insane.materialMedia.material.Material;
import br.ufmg.dees.insane.materialMedia.material.VonMises;
import br.ufmg.dees.insane.util.IMatrix;
import br.ufmg.dees.insane.util.IVector;

/** A class representing a VonMissesConstModel
 * @author jamile
 * 23/09/2005
 */
public class VonMisesConstModel extends ElastoPlasticConstModel {
    
   private static final long serialVersionUID = 1L;

	/** The internal variable in strain space used in associative plasticity.*/
    public final String ALPHA = "ALPHA";
    
    /** The interactive internal variable in strain space used in associative plasticity.*/
    public final String ITE_ALPHA = "ITE_ALPHA";
 
    /**Constructs this Constitutive Model.*/
    public VonMisesConstModel() {
    }
    
    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.materialMedia.constitutiveModel.ConstitutiveModel#getLabel()
     */
    public String getLabel() {
        return "VonMisesConstModel";
    }
    
    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.materialMedia.constitutiveModel.ElastoPlasticConstModel#getNumInternalVar(br.ufmg.dees.insane.materialMedia.material.Material)
     */
    public int getNumInternalVar(Material mat){
    	double H = (mat.getMaterialValues(((VonMises)(mat)).HARDENING_MODULUS).doubleValue());
        if(H == 0)return 0;
        else return 1; 
    }

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.materialMedia.constitutiveModel.ElastoPlasticConstModel#yieldHessian(br.ufmg.dees.insane.util.IVector, br.ufmg.dees.insane.util.IVector, br.ufmg.dees.insane.analysisModel.AnalysisModel)
     */
    public IMatrix yieldHessian(IVector s, IVector q, AnalysisModel am) {
        double J2 = am.getJ2(s);     
        double seq = Math.sqrt(3.0 * J2);
        double seq3 = seq*seq*seq;
        IMatrix A = new IMatrix(6,6);
        IMatrix B = new IMatrix(6,6);
        IMatrix H = new IMatrix(this.dimA,this.dimA);
        IVector ai = new IVector(6);
        IMatrix t = new IMatrix(am.getNumberOfDualInternalVariables(),am.getNumberOfDualInternalVariables()); 
        t.vecTensor3D(am.expandVector(s));
        A.setElement(0,0,-Math.pow(2.0*t.getElement(0,0)-t.getElement(1,1)-t.getElement(2,2),2.0)/(4.0*seq3)+1.0/seq);
        A.setElement(1,0,-(2.0*t.getElement(0,0)-t.getElement(1,1)-t.getElement(2,2))*(2.0*t.getElement(1,1)-t.getElement(0,0)-t.getElement(2,2))/(4.0*seq3)-1.0/(2.0*seq));
        A.setElement(2,0,-(2.0*t.getElement(0,0)-t.getElement(1,1)-t.getElement(2,2))*(2.0*t.getElement(2,2)-t.getElement(0,0)-t.getElement(1,1))/(4.0*seq3)-1.0/(2.0*seq));
        A.setElement(3,0,-3.0*(2.0*t.getElement(0,0)-t.getElement(1,1)-t.getElement(2,2))*t.getElement(0,1)/(2.0*seq3));
        A.setElement(4,0,-3.0*(2.0*t.getElement(0,0)-t.getElement(1,1)-t.getElement(2,2))*t.getElement(0,2)/(2.0*seq3));
        A.setElement(5,0,-3.0*(2.0*t.getElement(0,0)-t.getElement(1,1)-t.getElement(2,2))*t.getElement(1,2)/(2.0*seq3));
        A.setElement(1,1,-Math.pow(2.0*t.getElement(1,1)-t.getElement(0,0)-t.getElement(2,2),2.0)/(4.0*seq3)+1.0/seq);
        A.setElement(2,1,-(2.0*t.getElement(1,1)-t.getElement(0,0)-t.getElement(2,2))*(2.0*t.getElement(2,2)-t.getElement(0,0)-t.getElement(1,1))/(4.0*seq3)-1.0/(2.0*seq));
        A.setElement(3,1,-3.0*(2.0*t.getElement(1,1)-t.getElement(0,0)-t.getElement(2,2))*t.getElement(0,1)/(2.0*seq3));
        A.setElement(4,1,-3.0*(2.0*t.getElement(1,1)-t.getElement(0,0)-t.getElement(2,2))*t.getElement(0,2)/(2.0*seq3));
        A.setElement(5,1,-3.0*(2.0*t.getElement(1,1)-t.getElement(0,0)-t.getElement(2,2))*t.getElement(1,2)/(2.0*seq3));
        A.setElement(2,2,-Math.pow(2.0*t.getElement(2,2)-t.getElement(0,0)-t.getElement(1,1),2.0)/(4.0*seq3)+1.0/seq);
        A.setElement(3,2,-3.0*(2.0*t.getElement(2,2)-t.getElement(0,0)-t.getElement(1,1))*t.getElement(0,1)/(2.0*seq3));
        A.setElement(4,2,-3.0*(2.0*t.getElement(2,2)-t.getElement(0,0)-t.getElement(1,1))*t.getElement(0,2)/(2.0*seq3));
        A.setElement(5,2,-3.0*(2.0*t.getElement(2,2)-t.getElement(0,0)-t.getElement(1,1))*t.getElement(1,2)/(2.0*seq3));
        A.setElement(3,3,-9.0*t.getElement(0,1)*t.getElement(0,1)/(seq3)+3.0/seq);
        A.setElement(4,3,-9.0*t.getElement(0,1)*t.getElement(0,2)/(seq3));
        A.setElement(5,3,-9.0*t.getElement(0,1)*t.getElement(1,2)/(seq3));
        A.setElement(4,4,-9.0*t.getElement(0,2)*t.getElement(0,2)/(seq3)+3.0/seq);
        A.setElement(5,4,-9.0*t.getElement(0,2)*t.getElement(1,2)/(seq3));
        A.setElement(5,5,-9.0*t.getElement(1,2)*t.getElement(1,2)/(seq3)+3.0/seq);
        for(int i=0; i<6; i++)
            for(int j=i; j<6; j++) A.setElement(i,j,A.getElement(j,i));
        for(int i=0; i<6; i++){
            A.getRow(i,ai);
            IMatrix rowt = new IMatrix(3,3);
            rowt.vecTensor3D(ai);
            IVector rowv = am.reduceTensor(rowt);
            for(int j=0; j<am.getNumberOfDualInternalVariables(); j++)
                B.setElement(i,j,rowv.getElement(j));
        }
        A.setZero();
        A.transpose(B);
        for(int i=0; i<6; i++){
            A.getRow(i,ai);
            IMatrix rowt = new IMatrix(3,3);
            rowt.vecTensor3D(ai);
            IVector rowv = am.reduceTensor(rowt);
            for(int j=0; j<am.getNumberOfDualInternalVariables(); j++)
                B.setElement(i,j,rowv.getElement(j));
        }
        for(int i=0; i<am.getNumberOfDualInternalVariables(); i++)
            for(int j=0; j<am.getNumberOfDualInternalVariables(); j++)
                H.setElement(i,j,B.getElement(i,j)); 
        return H;
    }

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.materialMedia.constitutiveModel.ElastoPlasticConstModel#yieldGradStress(br.ufmg.dees.insane.util.IVector, br.ufmg.dees.insane.util.IVector, br.ufmg.dees.insane.analysisModel.AnalysisModel, java.util.HashMap)
     */
    public IVector yieldGradStress(IVector s, IVector q, AnalysisModel am, HashMap<Object, Object> hm) {        
        IVector dJ2dSIG = am.getdJ2dSIG(s);     
        double J2 = am.getJ2(s);     
        double dFdJ2 = 0.5 * Math.sqrt(3.0 / J2);
        dJ2dSIG.scale(dFdJ2);
        hm.put(this.dFdSIG,dJ2dSIG);   
        return ((IVector)(hm.get(this.dFdSIG)));
    }
    
    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.materialMedia.constitutiveModel.ElastoPlasticConstModel#yieldGradIntVar(br.ufmg.dees.insane.util.IVector, br.ufmg.dees.insane.util.IVector, br.ufmg.dees.insane.materialMedia.material.Material, java.util.HashMap)
     */
    public IVector yieldGradIntVar(IVector s, IVector q, Material mat, HashMap hm) {
        if(this.getNumInternalVar(mat) > 0)
            ((IVector)(hm.get(this.dFdq))).setElement(0,1.0);              
        return ((IVector)(hm.get(this.dFdq)));
    }
    
    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.materialMedia.constitutiveModel.ConstitutiveModel#getNumberOfVariables()
     */
    public int getNumberOfVariables() {
        return 7;
    }
    
    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.materialMedia.constitutiveModel.ConstitutiveModel#getNumberOfPreviousVariables()
     */
    public int getNumberOfPreviousVariables(){
        return 2;
    }
    
    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.materialMedia.constitutiveModel.ConstitutiveModel#update(java.util.HashMap, java.util.HashMap)
     */
    public void update(HashMap<Object, Object> previous, HashMap<Object, Object> cv) {
        previous.put(this.PLASTIC_DEFORM, cv.get(this.ITE_PLASTIC_DEFORM));
        previous.put(this.ALPHA, cv.get(this.ITE_ALPHA));
    }
    
    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.materialMedia.constitutiveModel.ConstitutiveModel#init(java.util.HashMap, java.util.HashMap, br.ufmg.dees.insane.analysisModel.AnalysisModel, br.ufmg.dees.insane.materialMedia.material.Material)
     */
    public void init(HashMap<Object, Object> previous, HashMap<Object, Object> cv, AnalysisModel am, Material mat) {
    	this.dimA = am.getNumberOfDualInternalVariables() + this.getNumInternalVar(mat);
    	previous.put(this.PLASTIC_DEFORM, new IVector(am.getNumberOfDualInternalVariables()));
        cv.put(this.ITE_PLASTIC_DEFORM, new IVector(am.getNumberOfDualInternalVariables()));
        previous.put(this.ALPHA, new IVector(this.dimA));
        cv.put(this.ITE_ALPHA, new IVector(this.dimA));
        cv.put(this.PLASTIC_MULTIPLIER, new Double(0.0));
        cv.put(this.ALGORIT_MOD, new IMatrix(am.getNumberOfDualInternalVariables(),am.getNumberOfDualInternalVariables()));
        cv.put(this.dFdSIG, new IVector(am.getNumberOfDualInternalVariables()));
        cv.put(this.dFdq, new IVector(this.getNumInternalVar(mat)));
        cv.put(this.DENOM, new Double(0.0)); 
    }
    
    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.materialMedia.constitutiveModel.ConstitutiveModel#init(java.util.HashMap, java.util.HashMap, br.ufmg.dees.insane.analysisModel.AnalysisModel, br.ufmg.dees.insane.materialMedia.material.Material)
     */
    public void init(HashMap<Object, Object> previous, HashMap<Object, Object> cv, ContinuousPointModel am, Material mat) {
        previous.put(this.PLASTIC_DEFORM, new IVector(am.getNumberOfDualInternalVariables()));
        cv.put(this.ITE_PLASTIC_DEFORM, new IVector(am.getNumberOfDualInternalVariables()));
        previous.put(this.ALPHA, new IVector(this.dimA));
        cv.put(this.ITE_ALPHA, new IVector(this.dimA));
        cv.put(this.PLASTIC_MULTIPLIER, new Double(0.0));
        cv.put(this.ALGORIT_MOD, new IMatrix(am.getNumberOfDualInternalVariables(),am.getNumberOfDualInternalVariables()));
        cv.put(this.dFdSIG, new IVector(am.getNumberOfDualInternalVariables()));
        cv.put(this.dFdq, new IVector(this.getNumInternalVar(mat)));
        cv.put(this.DENOM, new Double(0.0)); 
    }
    
    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.materialMedia.constitutiveModel.ElastoPlasticConstModel#getInternalVar(br.ufmg.dees.insane.materialMedia.material.Material, java.util.HashMap)
     */
    public IVector getInternalVar(Material mat, HashMap hm){
        if (this.getNumInternalVar(mat) == 0) return null;
        return ((IVector)hm.get(this.ITE_ALPHA));
    }
    
    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.materialMedia.constitutiveModel.ElastoPlasticConstModel#internalVarStress(br.ufmg.dees.insane.util.IVector, br.ufmg.dees.insane.materialMedia.material.Material)
     */
    public IVector internalVarStress(IVector alpha, Material mat){
        if (this.getNumInternalVar(mat) == 0) return null;        
        double H = (mat.getMaterialValues(((VonMises)(mat)).HARDENING_MODULUS).doubleValue());
        IVector q = new IVector(this.dimA);
        q.scale(-H,alpha);
        return q;
    }
    
    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.materialMedia.constitutiveModel.ElastoPlasticConstModel#yieldFunction(br.ufmg.dees.insane.util.IVector, br.ufmg.dees.insane.util.IVector, br.ufmg.dees.insane.analysisModel.AnalysisModel, br.ufmg.dees.insane.materialMedia.material.Material)
     */
    public double yieldFunction(IVector s, IVector q, AnalysisModel am, Material mat){
       double J2 = am.getJ2(s);     
       double fy = mat.getMaterialValues(((VonMises)(mat)).YIELDING).doubleValue();
       double f = Math.sqrt(3.0 * J2) - fy;
       if(this.getNumInternalVar(mat) > 0) f += q.getElement(0);
       return f;
    }
    
    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.materialMedia.constitutiveModel.ElastoPlasticConstModel#plasticModuli(br.ufmg.dees.insane.util.IVector, br.ufmg.dees.insane.materialMedia.material.Material)
     */
    public IMatrix plasticModuli(IVector alpha, Material mat){
        if(this.getNumInternalVar(mat) == 0){
        	IMatrix D = new IMatrix(dimA, dimA);
        	D.setZero();
        	return D;
        }
        double H = mat.getMaterialValues(((VonMises)(mat)).HARDENING_MODULUS).doubleValue();
        IMatrix D = new IMatrix(dimA, dimA);
        D.setElement(0,0,H);
        return D;
    }
    
    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.materialMedia.constitutiveModel.ElastoPlasticConstModel#setPlasticVar(br.ufmg.dees.insane.util.IVector, br.ufmg.dees.insane.util.IVector, br.ufmg.dees.insane.materialMedia.material.Material, java.util.HashMap)
     */
    public void setPlasticVar(IVector ep, IVector alpha, Material mat, HashMap<Object, Object> hm){
        hm.put(hm.get(this.ITE_PLASTIC_DEFORM),ep);
        if(this.getNumInternalVar(mat) == 0) return;
        hm.put(hm.get(this.ITE_ALPHA),alpha);        
    }

}
